// 
// @Auther: by wujehy
// @Email:wujehy@qq.com
// @Data:2021/2/17.
// @Time:下午1:48.
// 
//

#include "TestApp.h"
#include <thread>
#include "Client.h"
#include <sstream>

//NOTE 精简代码的方式, 直接声明符号即可获取实现部分的方法. 该方法不能使用static 声明 即可
std::shared_ptr<Client> getClientPtr();

static void proc_request(Dart_Port callbackPort, std::unique_ptr<RequestDataType> req);

void TestFunc_Sync(Dart_Port callbackPort, int time)
{
    // NOTE wujehy : 同步的方式是 同一个线程里面操作, 会阻塞线程
    debug_console_log( "TestFunc_Sync enter ... 1  " );

    for (int i = 0; i < time; ++i)
    {
        std::this_thread::sleep_for( std::chrono::seconds( 1 ));
        debug_console_log( "TestFunc_Sync sleep ... 2 " );
    }

    callDartCallbackData( callbackPort, 200, "TestFunc_Sync callback 3 " );
    debug_console_log( "TestFunc_Sync end ... 4 " );
}

void TestFunc_Async(Dart_Port callbackPort, int time)
{
    // NOTE wujehy : 同步的方式是 同一个线程里面操作, 不会阻塞线程
    debug_console_log( "TestFunc_Async enter ... 1 " );

    if (getClientPtr() == nullptr)
    {
        // 直接结束
        callDartCallbackData( callbackPort, 401, "客户端未初始化 2 " );
        // 直接结束
        debug_console_log( "TestFunc_Async stop : client not init  ... 3 " );
        return;
    }

    getClientPtr()->threadPool.appendTask(
            [callbackPort, time]()
            {
                debug_console_log( "TestFunc_Async task enter ... 3 " );
                for (int i = 0; i < time; ++i)
                {
                    std::this_thread::sleep_for( std::chrono::seconds( 1 ));
                    debug_console_log( "TestFunc_Async sleep ... 4 " );
                }
                callDartCallbackData( callbackPort, 200, "TestFunc_Async callback 5 " );
                debug_console_log( "TestFunc_Async task end ... 6 " );
            } );

    debug_console_log( "TestFunc_Async end ... 2 " );
}


// 自定义结构适合自己封装协议的时候 , 请求包和响应包 封装号后 通过网络异步 处理
// NOTE wujehy 这里模拟一个 异步回包的情况
void TestFunc_Customize(
        Dart_Port callbackPort,
        int code, const char *msg,
        int value1_bool, int value2_int32,
        const char *value3_strData,
        const char *value4_bytes_data,
        int value4_bytes_data_len)
{
    debug_console_log( "TestFunc_Customize enter ..." );
    if (getClientPtr() == nullptr)
    {
        // 直接结束
        callDartCallbackData( callbackPort, 401, "客户端未初始化 2 " );
        // 直接结束
        debug_console_log( "TestFunc_Customize stop : client not init  ...   " );
        return;
    }

    // 数据准备 , 这部分操作 很快 实践忽略不计

    RequestDataType *requestData = new RequestDataType;
    requestData->status = (value1_bool == 1);
    requestData->taskid = value2_int32;
    requestData->type = 1;
    requestData->token = value3_strData;
    requestData->data = std::string( value4_bytes_data, value4_bytes_data_len );

    getClientPtr()->threadPool.appendTask(
            [callbackPort, requestData]()
            {
                std::unique_ptr<RequestDataType> requestData_uptr = std::unique_ptr<RequestDataType>( requestData );
                std::this_thread::sleep_for( std::chrono::seconds( 1 ));
                proc_request( callbackPort, std::move( requestData_uptr ));
            } );

    debug_console_log( "TestFunc_Customize end ..." );
}

// 这里的处理 和 flutter 的 isolata的 send() 的 message参数是一致的
static void proc_request(Dart_Port callbackPort, std::unique_ptr<RequestDataType> req)
{
    // 处理
    std::stringstream sslog;
    sslog << "proc_request taskid = " << req->taskid << " token = " << req->token;
    debug_console_log( sslog.str().c_str());
    // 回包

    // 回报处理模块
    Dart_CObject dart_object;
    dart_object.type = Dart_CObject_kArray;
    dart_object.value.as_array.length = 7;
    Dart_CObject dartCObjectType;
    dartCObjectType.type = Dart_CObject_kInt32;
    dartCObjectType.value.as_int32 = 1;


    Dart_CObject dartCObjectCode;
    dartCObjectCode.type = Dart_CObject_kInt32;
    dartCObjectCode.value.as_int32 = 200;

    Dart_CObject dartCObjecterrormsg;
    dartCObjecterrormsg.type = Dart_CObject_kString;
    dartCObjecterrormsg.value.as_string = (char*)"callback errmsg";

    Dart_CObject dartCObjectTaskid;
    dartCObjectTaskid.type = Dart_CObject_kInt32;
    dartCObjectTaskid.value.as_int32 = req->taskid;

    Dart_CObject dartCObjectReqType;
    dartCObjectReqType.type = Dart_CObject_kInt32;
    dartCObjectReqType.value.as_int32 = req->type;


    Dart_CObject dartCObjectjwtToken;
    dartCObjectjwtToken.type = Dart_CObject_kString;
    dartCObjectjwtToken.value.as_string = (char *) req->token.c_str();


    Dart_CObject dartCObjectBody;
    dartCObjectBody.type = Dart_CObject_kTypedData;
    dartCObjectBody.value.as_typed_data.type = Dart_TypedData_kUint8;
    dartCObjectBody.value.as_typed_data.length = req->data.length();
    dartCObjectBody.value.as_typed_data.values = (uint8_t *) req->data.c_str();
//
    _Dart_CObject *dartCObjects[] = {&dartCObjectType,
                                     &dartCObjectCode,
                                     &dartCObjecterrormsg,
                                     &dartCObjectTaskid,
                                     &dartCObjectReqType,
                                     &dartCObjectjwtToken,
                                     &dartCObjectBody};
//
    dart_object.value.as_array.values = dartCObjects;
    bool result = callDartCallBack( callbackPort, &dart_object );
    if (!result)
    {
        warn_console_log( "proc_request callback false" );
    } else
    {
        debug_console_log( "proc_request callback success" );
    }

}

